﻿#ifndef DESCRIPTION_H
#define DESCRIPTION_H

#include <QObject>
#include <QXmlStreamWriter>
#include "device.h"
#include "objectfactory.h"
#include "step.h"
#include <QThread>
#include <QCoreApplication>
#include <QFile>

#include "rs232.h"
#include "ethernet.h"
#include "jakarobot.h"
#include "auborobot.h"
#include "delay.h"
#include "wordopcontrolled.h"
#include "movejoint.h"
#include "snap.h"
#include "recognize.h"
#include "step.h"
#include "virtualdevice.h"
#include "seatdetectionparameter.h"

class Description;

class DescriptionThread : public QThread{
    Q_OBJECT
public:
    explicit DescriptionThread(QObject *parent = nullptr){
        m_IsLoadXMLFile = false;
        m_IsAllDevicesInitialized = false;
        m_IsRunnable = false;
    }

    void SetSeatDetectionParameter(SeatDetectionParameter* pSeatDetectionParameter){
        m_pSeatDetectionParameter = pSeatDetectionParameter;
    }

signals:
    void SendCommandToMainWindow(QVariant data);

private slots:
    void ReceiveCommandFromDevice(QVariant data){
        emit SendCommandToMainWindow(data);
    }

private:
    QList<Device *>     m_pDevices;
    QList<Step *>       m_pSteps;
    QString             m_strXMLFilePath;

    bool                m_IsLoadXMLFile;
    bool                m_IsAllDevicesInitialized;
    bool                m_IsRunnable;

    SeatDetectionParameter* m_pSeatDetectionParameter;

private:
    Device *FindDeviceById(QString strID){
        foreach (Device *pDevice, m_pDevices) {
            if (pDevice->getStrID() == strID) {
                return pDevice;
            }
        }

        return NULL;
    }

public:
    void SetRunnable(bool runnable){
        m_IsRunnable = runnable;
    }
    void SetXMLFilePath(QString str){m_strXMLFilePath = str;}
    void AddDevice(Device *pDevice) { m_pDevices.append(pDevice); }
    void AddStep(Step *pStep) { m_pSteps.append(pStep); }
    void InitAllDevices(){
        foreach (Device *pDevice, m_pDevices) {
            pDevice->SetSeatDetectionParameter(m_pSeatDetectionParameter);
            pDevice->initDevice();

            connect(pDevice,&Device::SendCommandToDescription,this,&DescriptionThread::ReceiveCommandFromDevice);
        }
    }

    void ConvertDeviceID(){
        foreach (Step *pStep, m_pSteps) {
            foreach(Operation* pOperation, pStep->GetOperations()){
                Device* pDevice = FindDeviceById(pOperation->strDeviceID());
                pOperation->SetDevice(pDevice);
            }
        }
    }

    void ReadXML(const QString &filePath){
        ObjectFactory::registerClass<Delay>();
        ObjectFactory::registerClass<WordopControlLED>();
        ObjectFactory::registerClass<MoveJoint>();
        ObjectFactory::registerClass<RS232>();
        ObjectFactory::registerClass<Ethernet>();
        ObjectFactory::registerClass<JakaRobot>();
        ObjectFactory::registerClass<AuboRobot>();
        ObjectFactory::registerClass<VirtualDevice>();
        ObjectFactory::registerClass<Step>();
        ObjectFactory::registerClass<Snap>();
        ObjectFactory::registerClass<Recognize>();
        QList<QString> toolsList;
        QFile file(filePath);

        if (!file.open(QIODevice::ReadOnly)) {
            qWarning() << "Unable to open file:" << filePath;
            return;
        }

        QXmlStreamReader xmlReader(&file);

        // 读取 XML 直到结束
        while (!xmlReader.atEnd() && !xmlReader.hasError()) {
            xmlReader.readNext();

            // 如果是 Description 元素的开始
            if (xmlReader.isStartElement() && xmlReader.name() == QStringLiteral("Description")) {
                // 读取 description 元素内部
                while (!(xmlReader.tokenType() == QXmlStreamReader::EndElement
                         && xmlReader.name() == QStringLiteral("Description"))) {
                    xmlReader.readNext();

                    if (xmlReader.isStartElement() && xmlReader.name() == QStringLiteral("Devices")) {
                        while (!(xmlReader.tokenType() == QXmlStreamReader::EndElement
                                 && xmlReader.name() == QStringLiteral("Devices"))) {
                            xmlReader.readNext();
                            if (xmlReader.isStartElement()) {
                                QString className = xmlReader.name().toString();
                                Device *pDevice = (Device *) ObjectFactory::createObject(
                                    className.toLatin1());
                                if (pDevice != NULL) {
                                    pDevice->readFromXML(xmlReader);
                                    //pDevice->initDevice();
                                    this->AddDevice(pDevice);
                                }else{
                                    qDebug() << "ObjectFactory createObject is NULL!";
                                }
                            }
                        }
                    }

                    if (xmlReader.isStartElement() && xmlReader.name() == QStringLiteral("Steps")) {
                        while (!(xmlReader.tokenType() == QXmlStreamReader::EndElement
                                 && xmlReader.name() == QStringLiteral("Steps"))) {
                            xmlReader.readNext();
                            if (xmlReader.isStartElement()) {
                                QString className = xmlReader.name().toString();
                                Step *pStep = (Step *) ObjectFactory::createObject(className.toLatin1());
                                if (pStep != NULL) {
                                    pStep->readFromXML(xmlReader);
                                    this->AddStep(pStep);
                                }
                            }
                        }
                    }
                }
            }
        }

        // 检查 XML 是否有解析错误
        if (xmlReader.hasError()) {
            qWarning() << "XML error:" << xmlReader.errorString();
        }

        file.close();
    }

public:
    void run() override {
        // 加载XML文件
        if(!m_IsLoadXMLFile){
            ReadXML(m_strXMLFilePath);
            m_IsLoadXMLFile = true;
            qDebug() << "加载Description文件完成!";
        }
        // 初始化所有的设备
        if(!m_IsAllDevicesInitialized){
            // 查找所有的Operation中Device
            ConvertDeviceID();
            // 初始化Device
            InitAllDevices();
            m_IsAllDevicesInitialized = true;
            qDebug() << "初始化Description文件完成!";
        }
        // 运行所有的步骤
        if(m_IsRunnable)
        {
            foreach (Step *pStep, m_pSteps) {
                pStep->run();
                qDebug() << "Step is Running!" ;
                QThread::msleep(10);
            }
            qDebug() << "Run is finished!";
        }
    }
};

class DescriptionInitThread : public QThread {
    Q_OBJECT
public:
    explicit DescriptionInitThread(QObject *parent = nullptr){
    }

private:
    QList<Device *> m_pDevices;

public:
    void SetDevices(QList<Device *> devices){
        m_pDevices = devices;
    }

    Device *FindDeviceById(QString strID)
    {
        foreach (Device *pDevice, m_pDevices) {
            if (pDevice->getStrID() == strID) {
                return pDevice;
            }
        }

        return NULL;
    }

public:
    void run() override {
        // 在这里执行你的线程任务
        foreach (Device *pDevice, m_pDevices) {
            pDevice->initDevice();
        }

        qDebug() << "InitAllDevices is finished!";
    }
};

/**
 * @brief The DescriptionRunThread class
 * 运行Description的子线程
 */
class DescriptionRunThread : public QThread {
    Q_OBJECT
public:
    explicit DescriptionRunThread(QObject *parent = nullptr) : m_isRunning(false){
    }

private:
    QList<Step *> m_pSteps;
    bool m_isRunning;

public:
    void Stop(){
        m_isRunning = false;
    }

    void SetSteps(QList<Step *> steps){
        m_pSteps = steps;
    }

public:
    void run() override {
        // 在这里执行你的线程任务

        m_isRunning = true;
        foreach (Step *pStep, m_pSteps) {
            if(!m_isRunning){
                pStep->Stop();
                break;
            }
            pStep->run();
            qDebug() << "Step is Running!" ;
            QThread::msleep(10);
        }
        qDebug() << "Run is finished!";
    }
};

class Description : public QObject
{
    Q_OBJECT
public:
    Description();
    ~Description(){
        delete m_DescriptionRunThread;
    }

private:
    QList<Device *>     m_pDevices;
    QList<Step *>       m_pSteps;
    bool                m_isAllInitialized;
    bool                m_isRunning;

public:
    Device              *FindDeviceById(QString strID);
    QList<Step *>       GetSteps(){return m_pSteps;}
    QList<Device *>     GetDevices(){return m_pDevices;}
    void                SetAllInitialized(bool isInitialized){
        m_isAllInitialized = isInitialized;
    }

public:
    void clear();

public:
    void AddDevice(Device *pDevice) { m_pDevices.append(pDevice); }
    void AddStep(Step *pStep) { m_pSteps.append(pStep); }

public:
    bool writeXML(const QString &filePath);
    bool ReadXML(const QString &filePath);

    void initAllDevices();
    void uninitAllDevices();
    void run();
    void stop();
    void test();
    QList<Device *> pDevices() const;
    QList<Step *> pSteps() const;

private:
    DescriptionRunThread *m_DescriptionRunThread;

public slots:
    // 接收到虚拟设备的命令
    void ReceviceCmdFromVirtualDevice(QVariant variant);

signals:
    void SendCmdToMainWindow(QVariant variant);
};

#endif // DESCRIPTION_H
